import { ref, onMounted, onUnmounted, type Ref } from 'vue'

export interface WebSocketOptions {
    url?: string                     // WebSocket 连接地址（可选，默认使用环境变量）
    heartbeat?: {
        message?: string              // 心跳消息内容
        interval?: number             // 心跳间隔时间(ms)
    }
    reconnectConfig?: {
        retries?: number             // 重连次数
        delay?: number              // 重连延迟时间(ms)
    }
    onMessage?: (data: any) => void // 消息回调函数
    onError?: (event: Event) => void // 错误回调函数
    onClose?: (event: CloseEvent) => void // 关闭回调函数
    onOpen?: (event: Event) => void // 打开回调函数
}

export interface WebSocketResult {
    isConnected: Ref<boolean>            // 连接状态
    message: Ref<any>                    // 最新消息
    sendMessage: (data: any) => void     // 发送消息方法
    connect: () => void                 // 手动连接方法
    disconnect: () => void              // 手动断开方法
    reconnect: () => void              // 手动重连方法
}

const DEFAULT_WS_URL = import.meta.env.VITE_APP_WS_URL

if (!DEFAULT_WS_URL) {
    console.warn('WebSocket URL not found in environment variables (VITE_APP_WS_URL)')
}

export function useWebSocket(options: WebSocketOptions): WebSocketResult {
    const {
        url = DEFAULT_WS_URL,
        heartbeat = { message: 'ping', interval: 30000 },
        reconnectConfig = { retries: 3, delay: 3000 },
        onMessage,
        onError,
        onClose,
        onOpen
    } = options

    if (!url) {
        throw new Error('WebSocket URL is required but not provided in options or environment variables')
    }

    const ws = ref<WebSocket | null>(null)
    const isConnected = ref(false)
    const message = ref<any>(null)
    const reconnectCount = ref(0)
    let heartbeatTimer: NodeJS.Timeout | null = null
    let reconnectTimer: NodeJS.Timeout | null = null

    // 创建 WebSocket 连接
    const createWebSocket = () => {
        console.log('useWebSocket: 开始创建连接')
        
        if (ws.value?.readyState === WebSocket.OPEN) {
            console.log('useWebSocket: 连接已存在且处于打开状态')
            return
        }

        console.log('useWebSocket: 创建新的 WebSocket 连接', url)
        ws.value = new WebSocket(url)

        ws.value.onopen = (event: Event) => {
            console.log('useWebSocket: 连接已打开')
            isConnected.value = true
            reconnectCount.value = 0
            startHeartbeat()
            onOpen?.(event)
        }

        ws.value.onmessage = (event: MessageEvent) => {
            try {
                const data = JSON.parse(event.data)
                message.value = data
                onMessage?.(data)
            } catch (error) {
                message.value = event.data
                onMessage?.(event.data)
            }
        }

        ws.value.onerror = (event: Event) => {
            console.log('useWebSocket: 连接错误')
            isConnected.value = false
            onError?.(event)
            handleReconnect()
        }

        ws.value.onclose = (event: CloseEvent) => {
            console.log('useWebSocket: 连接关闭')
            isConnected.value = false
            onClose?.(event)
            handleReconnect()
        }
    }

    // 开始心跳
    const startHeartbeat = () => {
        console.log('useWebSocket: 开始心跳')
        stopHeartbeat() // 先清除可能存在的心跳定时器
        
        if (!heartbeat.message || !heartbeat.interval) {
            console.log('useWebSocket: 未配置心跳参数，不启动心跳')
            return
        }

        heartbeatTimer = setInterval(() => {
            if (ws.value?.readyState === WebSocket.OPEN) {
                console.log('useWebSocket: 发送心跳')
                sendMessage(heartbeat.message)
            } else {
                console.log('useWebSocket: 连接未打开，停止心跳')
                stopHeartbeat()
            }
        }, heartbeat.interval)
    }

    // 停止心跳
    const stopHeartbeat = () => {
        if (heartbeatTimer) {
            console.log('useWebSocket: 停止心跳')
            clearInterval(heartbeatTimer)
            heartbeatTimer = null
        }
    }

    // 处理重连
    const handleReconnect = () => {
        if (!reconnectConfig.retries || !reconnectConfig.delay) {
            console.log('useWebSocket: 未配置重连参数，不进行重连')
            return
        }

        if (reconnectCount.value >= reconnectConfig.retries) {
            console.log('useWebSocket: 达到最大重试次数')
            return
        }

        if (reconnectTimer) {
            console.log('useWebSocket: 清除已有的重连定时器')
            clearTimeout(reconnectTimer)
            reconnectTimer = null
        }

        // 只有在连接已关闭时才重连
        if (ws.value?.readyState === WebSocket.CLOSED) {
            reconnectTimer = setTimeout(() => {
                reconnectCount.value++
                console.log('useWebSocket: 尝试重连，第', reconnectCount.value, '次')
                createWebSocket()
            }, reconnectConfig.delay)
        } else {
            console.log('useWebSocket: 连接未完全关闭，跳过重连')
        }
    }

    // 发送消息
    const sendMessage = (data: any) => {
        if (!ws.value || ws.value.readyState !== WebSocket.OPEN) {
            console.warn('useWebSocket: 连接未打开，无法发送消息')
            return
        }

        try {
            const message = typeof data === 'string' ? data : JSON.stringify(data)
            ws.value.send(message)
        } catch (error) {
            console.error('useWebSocket: 发送消息错误', error)
        }
    }

    // 手动连接
    const connect = () => {
        console.log('useWebSocket: 手动连接')
        // 如果已经有连接，先断开
        if (ws.value) {
            disconnect()
        }
        createWebSocket()
    }

    // 手动断开
    const disconnect = () => {
        console.log('useWebSocket: 手动断开')
        stopHeartbeat()
        
        if (reconnectTimer) {
            clearTimeout(reconnectTimer)
            reconnectTimer = null
        }
        
        if (ws.value) {
            ws.value.close()
            ws.value = null
        }
        
        isConnected.value = false
        reconnectCount.value = 0
    }

    // 立即创建连接
    createWebSocket()

    return {
        isConnected,
        message,
        sendMessage,
        connect,
        disconnect,
        reconnect: handleReconnect
    }
} 